home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-25 | 60.8 KB | 1,585 lines |
- Subject: Motif FAQ (Part 3 of 6)
- Newsgroups: comp.windows.x.motif,comp.answers,news.answers
- From: ksall@cen.com (Ken Sall)
- Date: 11 Oct 1994 07:52:00 GMT
-
- Archive-name: motif-faq/part3
- Last-modified: OCT 10, 1994
- Posting-Frequency: monthly
- Organization: Century Computing, Inc.
- Version: 3.8
-
-
-
- -----------------------------------------------------------------------------
- Subject: 59) How can I replace characters typed with say a `*'? I want to
- replace input for password entry.
-
- [Last modified: April 93]
-
- Answer: In Motif 1.1 Use the modifyVerifyCallback to tell when input is
- received. Set text->ptr in the callback structure to '*'. This does not work
- under 1.0 because of an oversight in which changes to this are ignored. In
- Motif 1.0, what you can do is set the doit flag to 'false' so the text is not
- displayed. Then set a static boolean to True to prevent re-entrance. Next
- call XmTextReplace() to display your '*'. then reset your re-entrance flag to
- False. XmTextReplace() will call the XmNmodifyVerify callback. To prevent
- getting into an infinite loop, you need the re-entrance flag.
-
- The following program from Dan Heller illustrates this:
-
-
- --------------
- /* Written by Dan Heller. Copyright 1991, O'Reilly && Associates.
- * This program is freely distributable without licensing fees and
- * is provided without guarantee or warranty expressed or implied.
- * This program is -not- in the public domain. This program appears
- * in the Motif Programming Manual, O'Reilly Volume 6.
- */
-
- /* passwd.c -- prompt for a passwd. Meaning, all input looks like
- * a series of *'s. Store the actual data typed by the user in
- * an internal variable. Don't allow paste operations. Handle
- * backspacing by deleting all text from insertion point to the
- * end of text.
- */
- #include <Xm/Text.h>
- #include <Xm/LabelG.h>
- #include <Xm/RowColumn.h>
- #include <ctype.h>
-
- void check_passwd();
- char *passwd; /* store user-typed passwd here. */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- Widget toplevel, text_w, rowcol;
- XtAppContext app;
-
- toplevel = XtVaAppInitialize(&app, "Demos",
- NULL, 0, &argc, argv, NULL, NULL);
-
- rowcol = XtVaCreateWidget("rowcol",
- xmRowColumnWidgetClass, toplevel,
- XmNorientation, XmHORIZONTAL,
- NULL);
-
- XtVaCreateManagedWidget("Password:",
- xmLabelGadgetClass, rowcol, NULL);
- text_w = XtVaCreateManagedWidget("text_w",
- xmTextWidgetClass, rowcol, NULL);
-
- XtAddCallback(text_w, XmNmodifyVerifyCallback, check_passwd, NULL);
- XtAddCallback(text_w, XmNactivateCallback, check_passwd, NULL);
-
- XtManageChild(rowcol);
- XtRealizeWidget(toplevel);
- XtAppMainLoop(app);
- }
-
- void
- check_passwd(text_w, unused, cbs)
- Widget text_w;
- XtPointer unused;
- XmTextVerifyCallbackStruct *cbs;
- {
- char *new;
- int len;
-
- if (cbs->reason == XmCR_ACTIVATE) {
- printf("Password: %s\n", passwd);
- return;
- }
-
- if (cbs->text->ptr == NULL) { /* backspace */
- cbs->endPos = strlen(passwd); /* delete from here to end */
- if (cbs->endPos <= 0) return; /* catch null passwd - Mark Scoville */
- passwd[cbs->startPos] = 0; /* backspace--terminate */
- return;
- }
-
- if (cbs->text->length > 1) {
- cbs->doit = False; /* don't allow "paste" operations */
- return; /* make the user *type* the password! */
- }
-
- new = XtMalloc(cbs->endPos + 2); /* new char + NULL terminator */
- if (passwd) {
- strcpy(new, passwd);
- XtFree(passwd);
- } else
- new[0] = NULL;
- passwd = new;
- strncat(passwd, cbs->text->ptr, cbs->text->length);
- passwd[cbs->endPos + cbs->text->length] = 0;
-
- for (len = 0; len < cbs->text->length; len++)
- cbs->text->ptr[len] = '*';
- }
-
-
- -----------------------------------------------------------------------------
- Subject: 60) How can I best add a large piece of text to a scrolled text
- widget?
-
- [Last modified: Sept 94]
-
- [NOTE: This problem is probably only relevant for Motif 1.0 which probably no
- one is using anymore. If you know this to still be a problem, send mail to
- ksall@cen.com. I'll probably remove this question otherwise.]
-
- In some versions of Motif 1.0 even using XmTextSetString, it insists on adding
- the text one line at a time, adjusting the scroll bar each time. It looks
- awful and is slow.
-
- Answer: If you don't have this problem, use XmTextSetString to set all of the
- text in the widget. If you do have this slowdown problem even using
- XmTextSetString, unmanage the widget, add the text and then manage it again.
- This may cause the window to blink, but you have to put up with that or switch
- to a different version of Motif.
-
- -----------------------------------------------------------------------------
- Subject: 61) How can I highlight text in the Text widget?
-
- Answer: From: argv@zipcode.com (Dan Heller)
-
- If you don't need font or color changes, you can do all this using a Text
- widget very easily [in Motif 1.1, anyway].
-
- loop() {
- pos = offset_of_pattern_in_text_widget(pattern, text_w);
- search_len = strlen(pattern);
- XmTextSetHighlight(text_w, pos, pos+search_len,
- XmHIGHLIGHT_SELECTED);
- }
-
-
- There are two choices for highlighting: reverse video (HIGHLIGHT_SELECTED) and
- underlined (HIGHLIGHT_SECONDARY_SELECTED). Be careful that your users won't
- confuse your highlights with actual selections!
-
- -----------------------------------------------------------------------------
- Subject: 62) How can I select all of the text in a widget programmatically?
- So that some initial text is displayed, but anything typed replaces it.
-
- Answer: XmTextSetSelection(Text1, 0, XmTextGetLastPosition(Text1), event-
- >xbutton.time);
-
- where Text1 is the widget in question (obviously) and event is some event that
- triggered this call. You can use XtLastTimestampProcessed( display) instead
- of xbutton.time if you don't happen to have an event pointer handy.
-
-
- -----------------------------------------------------------------------------
- Subject: 63) How can I change colours of text in the Text widget? I want
- some of the text in one colour, some in another.
-
- Answer: You can't. Text stores an ordinary string, and points where
- `highlights' of various types begin and end. These highlights are all the
- control you have over components of the text. See the previous question.
-
-
- -----------------------------------------------------------------------------
- Subject: 64) How can I change the font of text in the Text widget? I want
- some of the text in one font, some in another.
-
- [Last modified: Sept 94]
-
- Answer: You can't in Text (see the previous question). If you wanted readonly
- text, you could do it by using a label instead. Label uses XmStrings, which
- can contain multiple character sets in the one string.
-
- If you are using Motif 2.0, however, XmStrings are now permitted in XmText
- widgets, which solves this particular problem.
-
- -----------------------------------------------------------------------------
- Subject: 65) Is there an emacs binding for the text widget?
-
- Answer: This set is due to Kee Hinckley (nazgul@utopia.com):
-
- *XmText.translations: #override\n\
- Ctrl <Key>b: backward-character()\n\
- Alt <Key>b: backward-word()\n\
- Meta <Key>b: backward-word()\n\
- Shift Alt <Key>b: backward-word(extend)\n\
- Shift Meta <Key>b: backward-word(extend)\n\
- Alt <Key>[: backward-paragraph()\n\
- Meta <Key>[: backward-paragraph()\n\
- Shift Alt <Key>[: backward-paragraph(extend)\n\
- Shift Meta <Key>[: backward-paragraph(extend)\n\
- Alt <Key><: beginning-of-file()\n\
- Meta <Key><: beginning-of-file()\n\
- Ctrl <Key>a: beginning-of-line()\n\
- Shift Ctrl <Key>a: beginning-of-line(extend)\n\
- Ctrl <Key>osfInsert: copy-clipboard()\n\
- Shift <Key>osfDelete: cut-clipboard()\n\
- Shift <Key>osfInsert: paste-clipboard()\n\
- Alt <Key>>: end-of-file()\n\
- Meta <Key>>: end-of-file()\n\
- Ctrl <Key>e: end-of-line()\n\
- Shift Ctrl <Key>e: end-of-line(extend)\n\
- Ctrl <Key>f: forward-character()\n\
- Alt <Key>]: forward-paragraph()\n\
- Meta <Key>]: forward-paragraph()\n\
- Shift Alt <Key>]: forward-paragraph(extend)\n\
- Shift Meta <Key>]: forward-paragraph(extend)\n\
- Ctrl Alt <Key>f: forward-word()\n\
- Ctrl Meta <Key>f: forward-word()\n\
- Ctrl <Key>d: kill-next-character()\n\
- Alt <Key>BackSpace: kill-previous-word()\n\
- Meta <Key>BackSpace: kill-previous-word()\n\
- Ctrl <Key>w: key-select() kill-selection()\n\
- Ctrl <Key>y: unkill()\n\
- Ctrl <Key>k: kill-to-end-of-line()\n\
- Alt <Key>Delete: kill-to-start-of-line()\n\
- Meta <Key>Delete: kill-to-start-of-line()\n\
- Ctrl <Key>o: newline-and-backup()\n\
- Ctrl <Key>j: newline-and-indent()\n\
- Ctrl <Key>n: next-line()\n\
- Ctrl <Key>osfLeft: page-left()\n\
- Ctrl <Key>osfRight: page-right()\n\
- Ctrl <Key>p: previous-line()\n\
- Ctrl <Key>g: process-cancel()\n\
- Ctrl <Key>l: redraw-display()\n\
- Ctrl <Key>osfDown: next-page()\n\
- Ctrl <Key>osfUp: previous-page()\n\
- Ctrl <Key>space: set-anchor()\n
-
-
- ! If you'd like the Delete key to work like backspace instead of deleting
- ! backwards, add the following definition to the lines above.
- ! <Key>osfDelete: delete-previous-character()\n\
-
- ! These aren't included because they could intefere with
- | menu accelerators (or vice versa)
- ! Alt <Key>p: backward-paragraph()\n\
- ! Meta <Key>p: backward-paragraph()\n\
- ! Shift Alt<Key>p: backward-paragraph(extend)\n\
- ! Shift Meta<Key>p: backward-paragraph(extend)\n\
- ! Alt <Key>w: copy-clipboard()\n\
- ! Meta <Key>w: copy-clipboard()\n\
- ! Ctrl Alt <Key>w: cut-clipboard()\n\
- ! Ctrl Meta <Key>w: cut-clipboard()\n\
- ! Alt <Key>y: paste-clipboard()\n\
- ! Meta <Key>y: paste-clipboard()\n\
- ! Alt <Key>f: forward-word()\n\
- ! Meta <Key>f: forward-word()\n\
- ! Alt <Key>n: forward-paragraph()\n\
- ! Meta <Key>n: forward-paragraph()\n\
- ! Shift Alt <Key>n: forward-paragraph(extend)\n\
- ! Shift Meta <Key>n: forward-paragraph(extend)\n\
- ! Shift Alt <Key>f: forward-word(extend)\n\
- ! Shift Meta <Key>f: forward-word(extend)\n\
- ! Alt <Key>d: kill-next-word()\n\
- ! Meta <Key>d: kill-next-word()\n\
- ! Alt <Key>h: select-all()\n\
- ! Meta <Key>h: select-all()\n\
-
- Similar sets of translations have been suggested by others.
-
- -----------------------------------------------------------------------------
- Subject: 66) How can I use a file as the text source for a Text widget?
-
- Answer: You can't do it directly like you can with the Athena Text widget.
- Instead, read the text from the file into a string (all of it!) and then use
- XmTextSetString. Alternatively, read blocks of characters and add them at the
- end of the text using XmTextInsertString. The following is an excerpt from
- Dan Heller's "file_browser.c":
-
- /* file_browser.c -- use a ScrolledText object to view the
- * contents of arbitrary files chosen by the user from a
- * FileSelectionDialog or from a single-line text widget.
- */
-
- ...
- struct stat statb;
-
- /* make sure the file is a regular text file and open it */
- if (stat(filename, &statb) == -1 ||
- (statb.st_mode & S_IFMT) != S_IFREG ||
- !(fp = fopen(filename, "r"))) {
- if ((statb.st_mode & S_IFMT) == S_IFREG)
- perror(filename); /* send to stderr why we can't read it */
- else
- fprintf(stderr, "%s: not a regular file0, filename);
- XtFree(filename);
- return;
- }
-
- /* put the contents of the file in the Text widget by allocating
- * enough space for the entire file, reading the file into the
- * allocated space, and using XmTextFieldSetString() to show the file.
- */
- if (!(text = XtMalloc((unsigned)(statb.st_size+1)))) {
- fprintf(stderr, "Can't alloc enough space for %s", filename);
- XtFree(filename);
- fclose(fp);
- return;
- }
-
- if (!fread(text, sizeof(char), statb.st_size+1, fp))
- fprintf(stderr, "Warning: may not have read entire file!0);
-
- text[statb.st_size] = 0; /* be sure to NULL-terminate */
-
- /* insert file contents in Text widget */
- XmTextSetString(text_w, text);
-
-
- -----------------------------------------------------------------------------
- Subject: 67) How can put Text in overstrike mode instead of insert?
-
- [Last modified: Sept 94]
-
- Answer: There is no direct way. This was posted by Edmond Pitt
- (ejp@bohra.cpg.oz) The correct answer to the question is to put the following
- in a modifyVerify callback, where 'mvcb' is the XmTextVerifyCallbackStruct,
- and 'overstriking' is defined by you:
-
- if (overstriking && mvcb->text->length == 1)
- {
- _XmTextDisableRedisplay(w,FALSE);
- XtCallActionProc(w,"delete-next-character",mvcb->event,0);
- _XmTextEnableRedisplay(w);
- }
-
- _XmText{Dis,En}ableRedisplay() are XmText{Dis,En}ableRedisplay() in 1.0, but
- X11R3 has no XtCallActionProc() anyway. For this environment you need my 1.0.3
- Text widget patches posted last year & available on request.
-
- An update was provided by Ingeborg (inca@osf.org):
-
- In 1.2 and later releases, there is an action function toggle-overstrike()
- which will toggle between overstrike and insert mode. Before 1.2.3, there is
- no visual difference, and at most one character will get overstruck. In 1.2.3,
- a block cursor was added as a visual cue to that the widget is in overstrike
- mode, and the code was fixed to overstrike the actual number of characters
- input (this makes a difference if you have preediting - for example in
- japanese).
-
- There is no default binding in 1.2, but the recommended key is osfInsert
- without modifiers. No resource exists.
-
-
- -----------------------------------------------------------------------------
- Subject: 68)* How can I make the Delete key do a Backspace? Related question:
- How can I swap Delete and Backspace?
-
- [Last modified: Oct 94]
-
- Answer: Put this in your .Xdefaults
-
- *XmText.translations: #override <Key>osfDelete: delete-previous-character()
-
-
- Additional information from David Kaelbling <drk@x.org>:
-
- You can also supply an arbitrary file name to xmbind (so you can conditionally
- run xmbind from your .xinitrc file based on the hostname, architecture,
- xdpyinfo output, or whatever).
-
- Some people prefer to use xmodmap to swap the keysyms for all applications,
- but what you're doing will work fine if you specify all of the virtual key
- bindings. The current bindings are stored on the root window -- use "xprop
- -root" and look for a _MOTIF_BINDINGS or _MOTIF_DEFAULT_BINDINGS property.
- OSF/Motif is also distributed with a "bindings" directory containing all the
- fallback virtkey binding files.
-
- There are several ways to do display-specific customization: make
-
- -----------------------------------------------------------------------------
- Subject: 69) TOPIC: LIST WIDGET
-
- -----------------------------------------------------------------------------
- Subject: 70) Should I create an XmList widget as a child of automatic
- XmScrolledWindow or use the XmCreateScrolledList() convenience function?
-
- Answer: With most implementations, the convenience function use internal hooks
- to give somewhat better scrolling performance.
-
- Thanks to Ken Lee, kenton@allegro.esd.sgi.com
-
- -----------------------------------------------------------------------------
- Subject: 71) How do I best put a new set of items into a list?
-
- Answer: Set the new list count and list by XtSetArgs and install them by
- XtSetValues.
-
- XmString list[SIZE];
- int list_size;
-
- XtSetArg (args[n], XmNitemCount, list_size); n++;
- XtSetArg (args[n], XmNitems, list); n++;
- XtSetValues (w, args, n);
-
-
- or similarly with XtVaSetValues:
-
-
- XtVaSetValues (w,
- XmNitemCount, list_size,
- XmNitems, list,
- NULL);
-
-
- Each time the list is reset by this the old contents are freed by the widget
- and the new supplied list is copied. Do *not* free the old list of items
- yourself as this would result in the space being freed twice. It is not
- necessary to remove the items one at a time, nor to "zero" out the list first.
-
- -----------------------------------------------------------------------------
- Subject: 72) Can I have strings with different fonts in a list?
-
- Answer: Yes. The strings are XmStrings. Each one can be created using a
- different character set using a different font.
-
-
- -----------------------------------------------------------------------------
- Subject: 73) Can I get a bitmap to show in a list item like I can in a Label?
- I want to place a bitmap along with some normal text in my list items.
-
- Answer: No. The list contains XmStrings, and these only allow text in various
- character sets. The workaround is to define your font containing the icons you
- want. Then you can create a fontlist containing your icon font and the font
- you want the text in, and then make your items multi-segment XmStrings where
- the first segment contains the code of the icon you want with a charset that
- matches the icon font in your fontlist and the second segment with a charset
- matching the text font.
-
-
- -----------------------------------------------------------------------------
- Subject: 74) Can I have items with different colours in a list?
-
- Answer: No. The list contains XmStrings, and these only allow text in various
- character sets. Since the items are XmStrings, you can already change the font
- of an item by replacing it with an item with the same text and a different
- charset tag. Adding support for color would require modification of the
- internal data structure in XmList as well as modification to the drawing
- routines. A possible workaround is to use a rowcolumn of buttons which can be
- individually set. However, you would have to do all list functionality
- yourself.
-
-
- -----------------------------------------------------------------------------
- Subject: 75) Can I grey out an item in a list? I want to make insensitive
- items in a list so that they cannot be selected.
-
- Answer:
-
- From W. Scott Meeks of OSF:
-
- Unfortunately, you can't do it directly since the list items aren't individual
- widgets. We've had other requests for this technology, but it didn't make the
- cut for 1.2; it should be in some future release.
-
- However, you can probably fake it in your application with some difficulty.
- First, a list item is an XmString, so you can specify a different charset for
- the item than for other items in the list and then specify a font in the
- list's fontlist that matches the charset and gives you the visual you want.
- The next problem is making the item unselectable. One idea would be to have
- the application keep track of the insensitive items and the items currently
- selected. Then you would set up a selection callback that when called would
- check the item selected against the list of insensitive items and if the
- selected item matched would deselect that item and reselect the previously
- selected items. Otherwise it would just update the application's list of
- selected items. The major drawback with this approach is that you'll get
- flashing whenever the list selects an item and your application immediately
- de-selects. Unfortunately I can't think of a way around this without mucking
- with the list internals.
-
- Another alternative suggested is to use instead a column of say read only text
- widgets which you can make insensitive.
-
- -----------------------------------------------------------------------------
- Subject: 76) Can I have multi-line items in a list?
- [Last modified: August 92]
-
- Answer: Motif 1.0 and 1.1 both have problems with multi-line items in a list.
- They should work okay in Motif 1.2.
-
- -----------------------------------------------------------------------------
- Subject: 77) How can I tell the position of selected items in a list?
-
- [Last modified: Oct 92]
-
- Answer: From W. Scott Meeks:
-
- 1) All XmList selection callbacks get an XmListCallbackStruct which includes
- the item selected and its position. In addition, the multiple and extended
- selection callbacks also get a list of the selected items. This approach
- requires that your application saves this information if you need it outside
- of the immediate callback.
-
- 2) At any time you can XtGetValues the XmNselectedItems and
- XmNselectedItemCount resources. The problem with this approach is that
- identical items may or may not show up in multiple times in this list and the
- position in the selectedItems list may not relate directly to the position in
- the items list.
-
- 3) You can call XmListGetSelectedPos on the list widget. This will return a
- list of the positions of all selected items.
-
- -----------------------------------------------------------------------------
- Subject: 78) TOPIC: FILE SELECTION BOX WIDGET
-
- -----------------------------------------------------------------------------
- Subject: 79) What is libPW.a and do I need it? My manual says I need to link
- in libPW.a to use the File Selection Box. I can't find it on my system.
-
- [Last modified: Sept 94]
-
- Answer: The libPW.a is the Programmers Workbench library which is an ATT
- product not included in Berkeley based systems, hence it is not found in SunOS
- or Ultrix, but is found on HP-UX (a Berkeley/ATT hybrid which chose ATT in
- this case). It contains the regex(3) routines (regcmp, regex). Some systems
- which don't have these in the libc.a need to link with -lPW. Some systems
- which have the regex(3) routines in there also have the libPW.a. If you have
- regex(3) in libc, and it works, don't link with libPW. If you don't have
- regex(3) in libc, and you don't have a libPW, then check some sites on the net
- for public domain replacements (several exist), or call your vendor.
-
- In most versions of Motif (see the doco), you can compile FileSB.c with
- -DNO_REGEX if you don't have it.
-
-
- Casper H.S. Dik (asper@fwi.uva.nl), Faculty of Mathematics & Computer Science,
- University of Amsterdam, sent this update for Solaris 2.x users:
-
- The regex and regcmp function are part of libgen in SVR4. Motif applications
- should be linked with -lgen. (However, some SVR4 implementations, especially
- those of vendors that once shipped SVR3 still contain libPW.)
-
- On Solaris 2.x system, you'll need libgen which is located in /usr/ccs/lib.
-
- -----------------------------------------------------------------------------
- Subject: 80) What are these compile errors: Undefined symbol _regcmp and
- _regex?
-
- [Last modified: Sept 94]
-
- Answer: You need to link in the libPW or libgen library - see previous
- question.
-
-
- -----------------------------------------------------------------------------
- Subject: 81) What's wrong with the Motif 1.0 File Selection Box? I can't set
- the directory, change the directory or get the file mask to work.
-
- Answer: The 1.0 File Selection Box is broken, and these don't work. They
- weren't fixed until Motif 1.04. Use these later versions of 1.0 or switch to
- Motif 1.1 where it changed a lot.
-
- Joe Hildebrand has a work-around for some of this: Before popping up an
- XmFileSelectionDialog, change to the directory you want. When a file is
- selected, check if it is a directory, so that we can change to it. i.e.
-
- static void show_file_box_CB(w, client_data, call_data)
- Widget w;
- Widget client_data;
- XmAnyCallbackStruct *call_data;
- {
- chdir("/users/hildjj/files");
- XtManageChild(client_data);
- }
-
- static void val_save(w, client_data, call_data)
- Widget w;
- Widget client_data;
- XmSelectionBoxCallbackStruct *call_data;
- {
- struct stat buf; /* struct stat is defined in stat.h */
- char *filename;
-
- /* get the file name from the FileSelectionBox */
- filename = SmX(call_data->value);
-
- /* get the status of the file named filename, and put it into buf */
- if (!stat(filename, &buf))
- {
- /* if it's a directory */
- /* if it's a directory */
- if(S_ISDIR(buf.st_mode))
- {
- /* change to that directory, and update the FileSelectionBox */
- chdir(filename);
- XmFileSelectionDoSearch(w, NULL);
- }
- else
- /* if it's a regular file */
- if(S_ISREG(buf.st_mode))
- /* ask if it should be overwritten */
- XtManageChild(valbox);
- else
- /* it's another kind of file. What type, i can't think of,
- but it might happen */
- pop_up_error_box(client_data, "Error saving file");
- }
- else /* we couldn't get the file status */
- {
- /* if it's because the file doesn't exist, we're golden */
- if (errno == ENOENT)
- save_file();
- else /* there is some other problem getting the status.
- e.g. bad path */
- pop_up_error_box(client_data, "Error saving file");
- }
- }
-
- this still doesn't implement the file masking stuff.
-
-
- -----------------------------------------------------------------------------
- Subject: 82) TOPIC: FORM WIDGET
-
-
- -----------------------------------------------------------------------------
- Subject: 83) Why don't labels in a Form resize when the label is changed?
- I've got some labels in a form. The labels don't resize whenever the label
- string resource is changed. As a result, the operator has to resize the window
- to see the new label contents. I am using Motif 1.1.
-
- Answer: This problem may happen to any widget inside a Form widget. The
- problem was that the Form will resize itself when it gets geometry requests
- from its children. If its preferred size is not allowed, the Form will
- disallow all geometry requests from its children. The workaround is that you
- should set any ancestor of the Form to be resizable. For the shell which
- contains the Form you should set the shell resource XmNallowShellResize to be
- True (by default, it is set to FALSE). There is currently an inconsistency on
- how resizing is being done, and it may get fixed in Motif 1.2.
-
- From db@sunbim.be (Danny Backx)
-
- Basically what you have to do is set the XmNresizePolicy on the Form to
- XmRESIZE_NONE. The facts seem to be that XmRESIZE_NONE does NOT mean "do not
- allow resizes". You may also have to set XmNresizable on the form to True.
-
- -----------------------------------------------------------------------------
- Subject: 84) How can I center a widget in a form?
-
- Answer: One of Motif's trickier questions. The problems are that: Form gives
- no support for centering, only for edge attachments, and the widget must stay
- in the center if the form or the widget is resized. Just looking at
- horizontal centering (vertical is similar) some solutions are:
-
- a. Use the table widget instead of Form.
-
- b. A hack free solution is from Dan Heller:
-
- /* Written by Dan Heller. Copyright 1991, O'Reilly && Associates.
- * This program is freely distributable without licensing fees and
- * is provided without guarantee or warranty expressed or implied.
- * This program is -not- in the public domain. This program is
- * taken from the Motif Programming Manual, O'Reilly Volume 6.
- */
-
- /* corners.c -- demonstrate widget layout management for a
- * BulletinBoard widget. There are four widgets each labeled
- * top-left, top-right, bottom-left and bottom-right. Their
- * positions in the bulletin board correspond to their names.
- * Only when the widget is resized does the geometry management
- * kick in and position the children in their correct locations.
- */
- #include <Xm/BulletinB.h>
- #include <Xm/PushBG.h>
-
- char *corners[] = {
- "Top-Left", "Top-Right", "Bottom-Left", "Bottom-Right",
- };
-
- static void resize();
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- Widget toplevel, bboard;
- XtAppContext app;
- XtActionsRec rec;
- int i;
-
- /* Initialize toolkit and create toplevel shell */
- toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
- &argc, argv, NULL, NULL);
-
- /* Create your standard BulletinBoard widget */
- bboard = XtVaCreateManagedWidget("bboard",
- xmBulletinBoardWidgetClass, toplevel, NULL);
-
- /* Set up a translation table that captures "Resize" events
- * (also called ConfigureNotify or Configure events). If the
- * event is generated, call the function resize().
- */
- rec.string = "resize";
- rec.proc = resize;
- XtAppAddActions(app, &rec, 1);
- XtOverrideTranslations(bboard,
- XtParseTranslationTable("<Configure>: resize()"));
-
- /* Create children of the dialog -- a PushButton in each corner. */
- for (i = 0; i < XtNumber(corners); i++)
- XtVaCreateManagedWidget(corners[i],
- xmPushButtonGadgetClass, bboard, NULL);
-
- XtRealizeWidget(toplevel);
- XtAppMainLoop(app);
- }
-
- /* resize(), the routine that is automatically called by Xt upon the
- * delivery of a Configure event. This happens whenever the widget
- * gets resized.
- */
- static void
- resize(w, event, args, num_args)
- CompositeWidget w; /* The widget (BulletinBoard) that got resized */
- XConfigureEvent *event; /* The event struct associated with the event */
- String args[]; /* unused */
- int *num_args; /* unused */
- {
- WidgetList children;
- int width = event->width;
- int height = event->height;
- Dimension w_width, w_height;
- short margin_w, margin_h;
-
- /* get handle to BulletinBoard's children and marginal spacing */
- XtVaGetValues(w,
- XmNchildren, &children,
- XmNmarginWidth, &margin_w,
- XmNmarginHeight, &margin_h,
- NULL);
-
- /* place the top left widget */
- XtVaSetValues(children[0],
- XmNx, margin_w,
-
- XmNy, margin_h,
- NULL);
-
- /* top right */
- XtVaGetValues(children[1], XmNwidth, &w_width, NULL);
-
- /* To Center a widget in the middle of the BulletinBoard (or Form),
- * simply call:
- * XtVaSetValues(widget,
- XmNx, (width - w_width)/2,
- XmNy, (height - w_height)/2,
- NULL);
- * and return.
- */
- XtVaSetValues(children[1],
- XmNx, width - margin_w - w_width,
- XmNy, margin_h,
- NULL);
- /* bottom left */
- XtVaGetValues(children[2], XmNheight, &w_height, NULL);
- XtVaSetValues(children[2],
-
- XmNx, margin_w,
- XmNy, height - margin_h - w_height,
- NULL);
- /* bottom right */
- XtVaGetValues(children[3],
- XmNheight, &w_height,
- XmNwidth, &w_width,
- NULL);
- XtVaSetValues(children[3],
- XmNx, width - margin_w - w_width,
- XmNy, height - margin_h - w_height,
- NULL);
- }
-
- c. No uil solution has been suggested, because of the widget size problem
-
- -----------------------------------------------------------------------------
- Subject: 85) How do I line up two columns of widgets of different types? I
- have a column of say label widgets, and a column of text widgets and I want to
- have them lined up horizontally. The problem is that they are of different
- heights. Just putting them in a form or rowcolumn doesn't line them up
- properly because the label and text widgets are of different height.
-
- If you want the geometry to look like this
-
- -------------------------------------
- | -------------------------- |
- |a label |Some text ||
- | -------------------------- |
- ------------------- |
- |a longer label |Some more text ||
- | ------------------- |
- | ---------------- |
- |a very long label |Even more text ||
- | ---------------- |
- -------------------------------------
-
- try
-
- /* Written by Dan Heller. Copyright 1991, O'Reilly && Associates.
- * This program is freely distributable without licensing fees and
- * is provided without guarantee or warranty expressed or implied.
- * This program is -not- in the public domain. This program is
- * taken from the Motif Programming Manual, O'Reilly Volume 6.
- */
-
- /* text_form.c -- demonstrate how attachments work in Form widgets.
- * by creating a text-entry form type application.
- */
-
- #include <Xm/PushB.h>
- #include <Xm/PushBG.h>
- #include <Xm/LabelG.h>
- #include <Xm/Text.h>
- #include <Xm/Form.h>
-
- char *prompts[] = {
- "Name:", "Phone:", "Address:",
- "City:", "State:", "Zip:",
- };
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- Widget toplevel, mainform, subform, label, text;
- XtAppContext app;
- char buf[32];
- int i;
-
- toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
- &argc, argv, NULL, NULL);
-
- mainform = XtVaCreateWidget("mainform",
- xmFormWidgetClass, toplevel,
- NULL);
-
- for (i = 0; i < XtNumber(prompts); i++) {
- subform = XtVaCreateWidget("subform",
- xmFormWidgetClass, mainform,
- /* first one should be attached for form */
- XmNtopAttachment, i? XmATTACH_WIDGET : XmATTACH_FORM,
- /* others are attached to the previous subform */
- XmNtopWidget, subform,
- XmNleftAttachment, XmATTACH_FORM,
- XmNrightAttachment, XmATTACH_FORM,
- NULL);
- label = XtVaCreateManagedWidget(prompts[i],
- xmLabelGadgetClass, subform,
- XmNtopAttachment, XmATTACH_FORM,
- XmNbottomAttachment, XmATTACH_FORM,
- XmNleftAttachment, XmATTACH_FORM,
- XmNalignment, XmALIGNMENT_BEGINNING,
- NULL);
- sprintf(buf, "text_%d", i);
- text = XtVaCreateManagedWidget(buf,
- xmTextWidgetClass, subform,
- XmNtopAttachment, XmATTACH_FORM,
- XmNbottomAttachment, XmATTACH_FORM,
- XmNrightAttachment, XmATTACH_FORM,
- XmNleftAttachment, XmATTACH_WIDGET,
- XmNleftWidget, label,
- NULL);
- XtManageChild(subform);
- }
- /* Now that all the forms are added, manage the main form */
- XtManageChild(mainform);
-
- XtRealizeWidget(toplevel);
- XtAppMainLoop(app);
- }
-
- If you resize horizontally it stretches the text widgets. If you resize
- vertically it leaves space under the bottom (if you don't resize, this is not
- problem).
-
- If you want the text widgets to be lined up on the left, as in
-
- ----------------------------------------
- | ------------------- |
- | a label |Some text ||
- | ------------------- |
- ------------------- |
- | a longer label |Some more text ||
- | ------------------- |
- | ------------------- |
- |a very long label |Even more text ||
- | ------------------- |
- ----------------------------------------
-
- try this
-
-
- /* Written by Dan Heller. Copyright 1991, O'Reilly && Associates.
- * This program is freely distributable without licensing fees and
- * is provided without guarantee or warranty expressed or implied.
- * This program is -not- in the public domain. This program is
- * taken from the Motif Programming Manual, O'Reilly Volume 6.
- */
-
- /* text_entry.c -- This demo shows how the RowColumn widget can be
- * configured to build a text entry form. It displays a table of
- * right-justified Labels and Text widgets that extend to the right
- * edge of the Form.
- */
- #include <Xm/LabelG.h>
- #include <Xm/RowColumn.h>
- #include <Xm/Text.h>
-
- char *text_labels[] = {
- "Name:", "Phone:", "Address:", "City:", "State:", "Zip:",
- };
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- Widget toplevel, rowcol;
- XtAppContext app;
- char buf[8];
- int i;
-
- toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
- &argc, argv, NULL, NULL);
-
- rowcol = XtVaCreateWidget("rowcolumn",
- xmRowColumnWidgetClass, toplevel,
- XmNpacking, XmPACK_COLUMN,
- XmNnumColumns, XtNumber(text_labels),
- XmNorientation, XmHORIZONTAL,
- XmNisAligned, True,
- XmNentryAlignment, XmALIGNMENT_END,
- NULL);
-
- /* simply loop thru the strings creating a widget for each one */
- for (i = 0; i < XtNumber(text_labels); i++) {
- XtVaCreateManagedWidget(text_labels[i],
- xmLabelGadgetClass, rowcol,
- NULL);
- sprintf(buf, "text_%d", i);
- XtVaCreateManagedWidget(buf,
- xmTextWidgetClass, rowcol,
- NULL);
- }
-
- XtManageChild(rowcol);
- XtRealizeWidget(toplevel);
- XtAppMainLoop(app);
- }
-
- This makes all objects exactly the same size. It does not resize in nice
- ways.
-
- If you want the text widgets lined up on the left, and the labels to be the
- size of the longest string, resizing nicely both horizontally and vertically,
- as in
-
- -------------------------------------
- | ---------------- |
- | a label |Some text ||
- | ---------------- |
- ---------------- |
- | a longer label |Some more text ||
- | ---------------- |
- | ---------------- |
- |a very long label |Even more text ||
- | ---------------- |
- -------------------------------------
-
-
- Answer: Do this: to get the widgets lined up horizontally, use a form but
- place the widgets using XmATTACH_POSITION. In the example, attach the top of
- the first label to the form, the bottomPosition to 33 (33% of the height).
- Attach the topPosition of the second label to 33 and the bottomPosition to 66.
- Attach the topPosition of the third label to 66 and the bottom of the label to
- the form. Do the same with the text widgets.
-
- To get the label widgets lined up vertically, use the right attachment of
- XmATTACH_OPPOSITE_WIDGET: starting from the one with the longest label, attach
- widgets on the right to each other. In the example, attach the 2nd label to
- the third, and the first to the second. To get the text widgets lined up,
- just attach them on the left to the labels. To get the text in the labels
- aligned correctly, use XmALIGNMENT_END for the XmNalignment resource.
-
- /* geometry for label 2
- */
- n = 0;
- XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNtopPosition, 66); n++;
- XtSetValues (label[2], args, n);
-
- /* geometry for label 1
- */
- n = 0;
- XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNbottomPosition, 66); n++;
- XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNtopPosition, 33); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
- XtSetArg (args[n], XmNrightWidget, label[2]); n++;
- XtSetValues (label[1], args, n);
-
- /* geometry for label 0
- */
- n = 0;
- XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNbottomPosition, 33); n++;
- XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
- XtSetArg (args[n], XmNrightWidget, label[1]); n++;
- XtSetValues (label[0], args, n);
-
- /* geometry for text 0
- */
- n = 0;
- XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNbottomPosition, 33); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
- XtSetArg (args[n], XmNleftWidget, label[0]); n++;
- XtSetValues (text[0], args, n);
-
- /* geometry for text 1
- */
- XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNtopPosition, 33); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNbottomPosition, 66); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
- XtSetArg (args[n], XmNleftWidget, label[1]); n++;
- XtSetValues (text[1], args, n);
-
- /* geometry for text 2
- */
- XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
- XtSetArg (args[n], XmNtopPosition, 66); n++;
- XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
- XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
- XtSetArg (args[n], XmNleftWidget, label[2]); n++;
- XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
- XtSetValues (text[2], args, n);
-
-
- -----------------------------------------------------------------------------
- Subject: 86) TOPIC: PUSHBUTTON WIDGET
-
- -----------------------------------------------------------------------------
- Subject: 87) Why can't I use accelerators on buttons not in a menu?
-
- [Last modified: Sept 94]
-
- Answer:
-
- It is apparently a difficult feature to implement, but OSF are considering
- this for the future. It is problematic trying to use the Xt accelerators since
- the Motif method interferes with this. one workaround suggested is to
- duplicate your non-menu button by a button in a menu somewhere, which does
- have a menu-accelerator installed. When the user invokes what they think is
- the accelerator for the button they can see Motif actually invokes the button
- on the menu that they can't see at the time. Another method is described below
- and was contributed by Harald Albrecht of Institute of Geometry and Practical
- Mathematics Rhine Westphalia Technical University Aachen (RWTH Aachen),
- Germany
-
-
- From albrecht@igpm.rwth-aachen.de Thu Jul 8 11:44:21 1993
-
- NOTE: Pointers to a more recent solution by the same author follow this code
- sample.
-
- My work-around of this problem looks like this: (I've written that code for a
- Motif Object Library in C++ so please forgive me for being object orientated!)
- The hack consists of a rewritten message loop which checks for keypresses
- <MAlt>+<key>. If MessageLoop() finds such a keypress HandleAcc() ist called
- and the widget tree is searched for a suitable widget with the right mnemonic.
-
-
- // --------------------------------------------------------------------------
- // traverse the widget tree starting with the given widget.
- //
- BOOL TraverseWidgetTree(Widget w, char *pMnemonic, XKeyEvent *KeyEvent)
- {
- Widget wChild;
- WidgetList ChildList;
- int NumChilds, Child;
- KeySym LabelMnemonic;
- char *pMnemonicString;
-
- // Check if the widget is a subclass of label -- then it may have an
- // accelerator attached...
- if ( XtIsSubclass(w, xmLabelWidgetClass) ) {
- // ok. Now: get the widget's mnemonic, convert it to ASCII and compare
- // it with the Key we're looking for.
- XtVaGetValues(w, XmNmnemonic, &LabelMnemonic, NULL);
- pMnemonicString = XKeysymToString(LabelMnemonic);
- if ( pMnemonicString &&
- (strcasecmp(pMnemonicString, pMnemonic) == 0) ) {
- // stimulate the keypress
- XmProcessTraversal((Widget)w, XmTRAVERSE_CURRENT);
- KeyEvent->type = KeyPress;
- KeyEvent->window = XtWindow(w);
- KeyEvent->subwindow = XtWindow(w);
- KeyEvent->state = 0;
- KeyEvent->keycode =
- XKeysymToKeycode(XtDisplay(w), XK_space);
- XSendEvent(XtDisplay(w), XtWindow(w),
- True,
- ButtonPressMask, (XEvent*) KeyEvent);
- KeyEvent->type = KeyRelease;
- XSendEvent(XtDisplay(w), XtWindow(w),
- True,
- ButtonReleaseMask, (XEvent*) KeyEvent);
- return True;
- }
- }
- // if this widget is a subclass of Composite check all the widget's
- // childs.
- if ( XtIsSubclass(w, compositeWidgetClass) ) {
- // if we're in a menu (or something like that) forget this leaf of the
- // widget tree!
- if ( XtIsSubclass(w, xmRowColumnWidgetClass) ) {
- unsigned char RowColumnType;
- XtVaGetValues(w, XmNrowColumnType, &RowColumnType, NULL);
- if ( RowColumnType != XmWORK_AREA ) return False;
- }
- XtVaGetValues(w, XmNchildren, &ChildList,
- XmNnumChildren, &NumChilds, NULL);
- for ( Child = 0; Child < NumChilds; ++Child ) {
- wChild = ChildList[Child];
- if ( TraverseWidgetTree(wChild, pMnemonic, KeyEvent) )
- return True;
- }
- }
- return False;
- } // TraverseWidgetTree
- // --------------------------------------------------------------------------
- // handle accelerators (keypress MAlt + key)
- //
- #define MAX_MAPPING 10
- BOOL HandleAcc(Widget w, XEvent *event)
- {
- Widget widget, OldWidget;
- static char keybuffer[MAX_MAPPING];
- int CharCount;
- static XComposeStatus composeStatus;
-
- // convert KeyPress to ASCII
- CharCount = XLookupString((XKeyEvent*) event,
- keybuffer, sizeof(keybuffer),
- NULL, &composeStatus);
- keybuffer[CharCount] = 0;
- // Only one char is alright -- then search the widget tree for a widget
- // with the right mnemonic
- if ( CharCount == 1 ) {
- keybuffer[0] = tolower(keybuffer[0]);
- widget = w;
- while ( (widget != NULL) &&
- !XtIsSubclass(widget, shellWidgetClass) ) {
- OldWidget = widget; widget = XtParent(widget);
- }
- if ( !widget ) widget = OldWidget;
- return TraverseWidgetTree(widget,
- keybuffer, (XKeyEvent*) event);
- }
- return False; // no-one found.
- } // HandleAcc
- // --------------------------------------------------------------------------
- // modified message loop
- // loops until the Boolean pFlag points to is set to False
- void MessageLoop(Boolean *pFlag)
- {
- XEvent nextEvent;
-
- while ( *pFlag ) {
- if ( XtAppPending(AppContext) ) {
- XtAppNextEvent(AppContext, &nextEvent);
- if ( nextEvent.type == KeyPress ) {
- // Falls es ein Tastendruck ist, bei dem auch noch die ALT-Taste
- // (=Modifier 1) gedrueckt ist, koennte es ein Accelerator sein!
- if ( nextEvent.xkey.state & Mod1Mask )
- if ( HandleAcc(XtWindowToWidget(nextEvent.xkey.display,
- nextEvent.xkey.window),
- &nextEvent) )
- continue; // Mitteilung konnte ausgeliefert werden
- // und darf daher nicht den ueblichen
- // Weg gehen!
- }
- XtDispatchEvent(&nextEvent);
- }
- }
- } // TApplication::MessageLoop
-
-
- Harald Albrecht albrecht@igpm.rwth-aachen.de Institute of Geometry and
- Practical Mathematics Rhine Westphalia Technical University Aachen (RWTH
- Aachen), Germany
-
- NOTE: Harald Albrecht has re-designed his solution so that you can assign
- hotkeys to *every* widget by placing a label near that widget. Get the code
- from:
-
- ftp.informatik.rwth-aachen.de (137.226.112.172)
- in: /pub/packages/Mnemonic/Mnemonic.tar.gz
-
- or from the WWW:
-
- file://134.130.161.30/arc/pub/unix/html/motifcorner.html
-
- -----------------------------------------------------------------------------
- Subject: 88) TOPIC: ICON WIDGET
-
- -----------------------------------------------------------------------------
- Subject: 89) How can I add multi-colored icons to my application?
-
- [Last modified: Sept 94]
-
- Answer: Get the Xpm (X PixMap file format) widgets. There is a tutorial in
- the directory ftp.x.org:/contrib/docs/xpm_tut and source code in the directory
- ftp.x.org:/contrib/libraries. Documentation is part of the tar file found in
- /contrib/libraries. The /contrib/libraries directory also contains xpm.FAQ.
-
- There is also a mailing list: xpm-talk@sophia.inria.fr.
-
- -----------------------------------------------------------------------------
- Subject: 90)+ How can I convert a Sun/GIF/TIFF image to a pixmap?
-
- [Last modified: Oct 94]
-
- Answer: An application called "xv" (interactive image display for the X Window
- System) is useful for displaying and converting many image formats. From the
- man page:
-
- xv is an X11 program that displays images in the GIF, JPEG,
- TIFF, PBM, PGM, PPM, X11 bitmap, PDS/VICAR, Sun Rasterfile,
- and PM formats on 1-, 2-, 4-, 6-, 8-, 16-, 24-, and 32-bit X
- displays. xv will also read compress-ed versions of these
- files.
-
- You can get "xv" (shareware by John Bradley et al) from:
-
- ftp://ftp.cis.upenn.edu/pub/xv
- or:
- ftp://ftp.x.org/R5contrib/xv-3.01.tar.gz
-
- Another useful conversion package is "pbm" (portable bitmap file format) by
- Jef Poskanzer et al, available from:
-
- ftp://ftp.x.org/R5contrib/netpbm-1mar1994.tar.gz
- or:
- ftp://ftp.x.org/R5contrib/pbmplus10dec91.tar.Z (much older :-)
-
- You might also want to check the X11 FAQ for additional conversion options:
-
- ftp://ftp.x.org/contrib/faqs/FAQ
-
- -----------------------------------------------------------------------------
- Subject: 91) TOPIC: LABEL WIDGET
-
- -----------------------------------------------------------------------------
- Subject: 92) How can I align the text in a label (button, etc) widget?
-
- Answer: The alignment for the label widget is controlled by the resource
- XmNalignment, and the default centers the text. Use this resource to change it
- to left or right alignment. However, when the label (or any descendant) is in
- a row column, and XmNisAligned is True (the default), the row column aligns
- text using its resource XmNentryAlignment. If you want simultaneous control
- over all widgets use this, but otherwise turn XmNisAligned off and do it
- individually.
-
-
- -----------------------------------------------------------------------------
- Subject: 93) Why doesn't label alignment work in a RowColumn?
-
- Answer: RowColumn has a resource XmNisAligned (default True) and and
- XmNentryAlignment (default XmALIGNMENT_BEGINNING). These control alignment of
- the labelString in Labels and descendants. Set XmNisAligned to False to turn
- this off.
-
- -----------------------------------------------------------------------------
- Subject: 94) How can I set a multiline label?
-
- [Last modified: September 92]
-
- Answer: In .Xdefaults
-
- *XmLabel*labelString: Here\nis\nthe\nLabel
-
- This method does not seem to work in some of the older Motif 1.0 versions.
-
- In code,
-
- char buf[128];
- XmString msg;
- sprintf(buf, "Here\nis\nthe\nLabel");
- msg = XmStringCreateLtoR(buf, XmSTRING_DEFAULT_CHARSET);
- XtSetArg (args[n], XmNlabelString, msg);
-
- Gives a four line label, using the escape sequence \n for a newline. However,
- XmStringCreateLtoR() is obsoleted from version 1.1 on, and may disappear.
- This is because it it is only in the AES as "trial-use" and has been proposed
- for removal from the AES. Realistically, it will probably not be removed from
- any backward compatible versions of Motif, but the potential is there. If it
- does disappear (or if you want to avoid using the non-AES compliant
- XmSTRING_DEFAULT_CHARSET), try this from Jean-Philippe Martin-Flatin
- <syj@ecmwf.co.uk>
-
- #include <Xm/Xm.h>
- #include <string.h>
-
- /*-----------------------------------------------------
- Create a new XmString from a char*
-
- This function can deal with embedded 'newline' and
- is equivalent to the obsolete XmStringCreateLtoR,
- except it does not use non AES compliant charset
- XmSTRING_DEFAULT_CHARSET
- ----------------------------------------------------*/
- XmString xec_NewString(char *s)
- {
- XmString xms1;
- XmString xms2;
- XmString line;
- XmString separator;
- char *p;
- char *t = XtNewString(s); /* Make a copy for strtok not to */
- /* damage the original string */
-
-
- separator = XmStringSeparatorCreate();
- p = strtok(t,"\n");
- xms1 = XmStringCreateSimple(p);
-
- while (p = strtok(NULL,"\n"))
- {
- line = XmStringCreateSimple(p);
- xms2 = XmStringConcat(xms1,separator);
- XmStringFree(xms1);
- xms1 = XmStringConcat(xms2,line);
- XmStringFree(xms2);
- XmStringFree(line);
- }
-
- XmStringFree(separator);
- XtFree(t);
- return xms1;
- }
-
-
- Do not use XmStringCreateSimple() - it does not process the newline character
- in the way you want.
-
- -----------------------------------------------------------------------------
- Subject: 95) How can I have a vertical label?
-
- Answer: Make a multiline label with one character per line, as in the last
- question. There is no way to make the text rotated by 90 degrees though.
-
-
- -----------------------------------------------------------------------------
- Subject: 96) How can I have a Pixmap in a Label?
-
- Answer: From Bob Hays (bobhays@spss.com)
-
- Pixmap px_disarm, px_disarm_insens;
-
- Widget Label1;
- Pixel foreground, background;
- Arg args[4];
- Arg arg[] = {
- { XmNforeground, &foreground },
- { XmNbackground, &background }
- };
-
- Label1 = XmCreateLabel ( Shell1, "Label1",
- (Arg *) NULL, (Cardinal) 0 );
- XtGetValues ( Label1, arg, XtNumber ( arg ) );
- px_disarm =
- XCreatePixmapFromBitmapData(display,
- DefaultRootWindow(display),
- mtn_bits, mtn_width, mtn_height,
- foreground,
- background,
- DefaultDepth(display,DefaultScreen(display)));
- px_disarm_insens =
- XCreatePixmapFromBitmapData(display,
- DefaultRootWindow(display),
- mtn_ins_bits, mtn_ins_width, mtn_ins_height,
- foreground,
- background,
- DefaultDepth(display,DefaultScreen(display)));
-
- n = 0;
- XtSetArg(args[n], XmNlabelType, XmPIXMAP); n++;
- XtSetArg(args[n], XmNlabelPixmap, px_disarm); n++;
- XtSetArg(args[n], XmNlabelInsensitivePixmap, px_disarm_insens ); n++;
- XtSetValues ( Label1, args, n );
- XtManageChild(Label1);
-
- That will cause the foreground and background of your pixmap to be inherited
- from the one that would be used by OSF/Motif when the label is displayed. The
- advantage is that this will utilize any resource values the user may have
- requested without looking explicitly into the resource database. And, you
- will have a pixmap handy if the application insensitizes the label (without an
- XmNlabelInsensitivePixmap your label will go empty if made insensitive).
-
- [Bob's original code was for a PushButton. Just change all Label to PushButton
- for them.]
-
- -----------------------------------------------------------------------------
- Subject: 97) TOPIC: DRAWING AREA WIDGET
-
- -----------------------------------------------------------------------------
- Subject: 98) How can I send an expose event to a Drawing Area widget? (or
- any other, come to that). I want to send an expose event so that it will
- redraw itself.
-
- Answer: Use the Xlib call
-
- XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, True)
-
- This clears the widget's window and generates an expose event in doing so.
- The widgets expose action will then redraw it. This uses a round trip
- request. An alternative, without the round trip is
-
- from orca!mesa!rthomson@uunet.uu.net (Rich Thomson):
-
- Widget da;
- XmDrawingAreaCallbackStruct da_struct;
-
- da_struct.reason = XmCR_EXPOSE;
- da_struct.event = (XEvent *) NULL;
- da_struct.window = XtWindow(da);
-
- XtCallCallbacks(da, XmNexposeCallback, (XtPointer) da_struct);
-
-
- -----------------------------------------------------------------------------
- Subject: 99) How can I know when a DrawingArea has been resized? It
- generates an expose event whn it is enlarged, but not when it is shrunk.
-
- Answer: Use the resize callback.
-
- -----------------------------------------------------------------------------
- Subject: 100) TOPIC: MENUS
-
- -----------------------------------------------------------------------------
- Subject: 101) How do I set the current choice in a radio box or an option
- menu?
-
- [Last modified: Sept 94]
-
- Answer: Set the XmNmenuHistory resource on its RowColumn parent.
-
- Thanks to Ken Lee, kenton@esd.sgi.com
-
- -----------------------------------------------------------------------------
- Subject: 102) How do I make a menu choice insensitive if it was created with
- XmVaCreateSimplePulldownMenu?
-
- [Last modified: Sept 94]
-
- Answer: According to the Motif manual, the buttons are named "button_n", where
- "n" is an integer starting from 0. You can use XtNameToWidget() to convert
- these names to widget ID's.
-
- Thanks to Ken Lee, kenton@esd.sgi.com
-
- -----------------------------------------------------------------------------
- Subject: 103) What can I put inside a menu bar?
-
- Answer: You can only put cascade buttons in menu bars. No pushbuttons, toggle
- buttons or gadgets are allowed. When you create a pulldown menu with parent a
- menu bar, its real parent is a shell widget.
-
- -----------------------------------------------------------------------------
- Subject: 104) Can I have a cascade button without a submenu in a pulldown
- menu?
-
- Answer: Yes you can. A cascade button has an activate callback which is called
- when you click on it and it doesn't have a submenu. It can have a mnemonic,
- but keyboard traversal using the arrow keys in the menu will skip over it.
-
- -----------------------------------------------------------------------------
- Subject: 105) Should I have a cascade button without a submenu in a pulldown
- menu?
-
- Answer: No. This is forbidden by the style guide. Technically you can do it
- (see previous question) but if you do it will not be Motif style compliant.
- This is unlikely to change - if a "button" is important enough to be in a
- pulldown menu bar with no pulldown, it should be a button elsewhere. (Mind
- you, you won't be able to put accelerators on it elsewhere though.)
-
- -----------------------------------------------------------------------------
- Subject: 106) What is the best way to create popup menus?
-
- [Last modified: August 92]
-
- Susan Murdock Thompson (from OSF): In general, create a popupMenu as the child
- from which you will be posting it from (ie: if you have a bulletinBoard with a
- PushButton in it and want MB2 on the pushButton to post the popupMenu, create
- the popupMenu as a child of the pushButton). [This parent-child relationship
- seems to make a big difference in the behavior of the popups.] Add an event
- handler to handle buttonPress events. You'll need to check for the correct
- button (what you've specified menuPost to be) before posting the menu.
-
- To create a popup that can be accessible from within an entire client window,
- create it as the child of the top-most widget (but not the shell) and add
- event handlers for the top-most widget and children widgets.
-
- ie:
-
- {
- ....
-
- XtManageChild(rc=XmCreateRowColumn(Shell1, "rc", NULL, 0));
- XtManageChild(label = XmCreateLabel(rc, "label", NULL, 0));
- XtManageChild(text = XmCreateText(rc, "text", NULL, 0));
- XtManageChild(pushbutton = XmCreatePushButton(rc, "pushbutton", NULL, 0));
-
- n = 0;
- XtSetArg(args[n], XmNmenuPost, "<Btn3Down>"); n++;
- popup = XmCreatePopupMenu(rc, "popup", args, n);
-
- XtAddEventHandler(rc, ButtonPressMask, False, PostMenu3, popup);
- XtAddEventHandler(text, ButtonPressMask, False, PostMenu3, popup);
- XtAddEventHandler(label, ButtonPressMask, False, PostMenu3, popup);
- XtAddEventHandler(pushbutton, ButtonPressMask, False, PostMenu3, popup);
-
- XtManageChild(m1 = XmCreatePushButton(popup, "m1", NULL, 0));
- XtManageChild(m2 = XmCreatePushButton(popup, "m2", NULL, 0));
- XtManageChild(m3 = XmCreatePushButton(popup, "m3", NULL, 0));
-
- XtAddCallback(m1, XmNactivateCallback, SayCB, "button M1");
- XtAddCallback(m2, XmNactivateCallback, SayCB, "button M2");
- XtAddCallback(m3, XmNactivateCallback, SayCB, "button M3");
- ...
- }
-
- /* where PostMenu3 is ... */
-
- PostMenu3 (w, popup, event)
- Widget w;
- Widget popup;
- XButtonEvent * event;
- {
- printf("menuPost = 3, button %d0, event->button);
-
- if (event->button != Button3)
- return;
- XmMenuPosition(popup, event);
- XtManageChild(popup);
- }
-
-
- -----------------------------------------------------------------------------
- END OF PART THREE
-
-